package com.app.system.permission.service;

import com.app.system.common.EncipherPwd;
import com.app.system.config.jwt.JwTUtils;
import com.app.system.jpa.JpaBaseDao;
import com.app.system.jpa.PageBean;
import com.app.system.jpa.Wrapper;
import com.app.system.permission.dao.UserInfoDao;
import com.app.system.permission.model.SysRole;
import com.app.system.permission.model.UserInfo;
import com.app.system.utils.WebUtils;
import com.app.system.utils.dataType.DateUtils;
import com.app.system.utils.exception.Precondition;
import com.google.common.collect.Maps;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.apache.shiro.subject.support.DefaultSubjectContext;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;

@Service
@SuppressWarnings("all")
@CacheConfig(cacheNames = {"userInfoCache"})
public class UserInfoService extends JpaBaseDao<UserInfo, Integer> {

    @Resource
    private UserInfoDao userInfoDao;
    @Resource
    private EncipherPwd encipherPwd;

    @Cacheable(key = "targetClass + methodName +#p0")
    public UserInfo findByUsername(String username) {
        return userInfoDao.findByUsername(username);
    }


    /**
     * 直接保存
     * 清空缓存
     *
     * @param userInfo
     */
    @CacheEvict(value = {"userInfoCache", "sysRoleCache", "sysPermissionCache"}, allEntries = true)
    @Override
    public synchronized void save(UserInfo userInfo) {
        this.userInfoDao.save(userInfo);
    }

    /**
     * 保存前验证用户名是否重复，以及首次时初始用户密码
     * 清空缓存
     *
     * @param userInfo
     */
    @CacheEvict(value = {"userInfoCache", "sysRoleCache", "sysPermissionCache"}, allEntries = true)
    @Transactional
    public synchronized void saveBeforeValidateUserName(UserInfo userInfo) {
        //验证用户名是否重复
        UserInfo validate = userInfoDao.findByUsername(userInfo.getUsername());
        Precondition.checkAjaxArguement(validate == null || (userInfo.getId() != null && validate.getId().intValue() == userInfo.getId().intValue()), "1111", "用户名重复");
        if (userInfo.getId() == null) {//首次初始密码
            Map<String, String> result = this.encipherPwd.getEncipherPwd(userInfo.getUsername());

            String newPassword = result.get("password");//加密后的密码
            String salt = result.get("salt");//生成密码时一并产生的盐值
            userInfo.setPassword(newPassword);
            userInfo.setSalt(salt);
        }
        this.userInfoDao.save(userInfo);
    }

    //清空缓存
    @CacheEvict(value = "userInfoCache", allEntries = true)
    public void updatePwd(Integer uid, String encipherPassword, String encipherSalt) {
        this.userInfoDao.updatePwd(uid, encipherPassword, encipherSalt);
    }

    //清空缓存
    @CacheEvict(value = {"userInfoCache", "sysRoleCache", "sysPermissionCache"}, allEntries = true)
    public void delByIds(List<Integer> ids) {
        this.userInfoDao.delByIds(ids);
    }

    /**
     * 分页处理
     * 此处不能配置缓存
     *
     * @return
     */
    public PageBean<UserInfo> findPageBean() {
        //查询语句
        StringBuffer query = new StringBuffer("distinct u from UserInfo u left join u.roleList r left join u.department d");
        //分页数据防止重复：多表关联
        StringBuffer countQuery = new StringBuffer("count(distinct u)");
        //默认排序(PageBean指定排序字段类型的话，则默认排序不使用)
        StringBuffer orderBy = new StringBuffer("u.id desc,u.state desc");

        Wrapper wrapper = new Wrapper(query, countQuery, orderBy);
        wrapper.initSearchParams();

        return this.pageHql(wrapper);
    }

    @Cacheable(key = "targetClass + methodName +#p0")
    public UserInfo findOneById(Integer id) {
        return this.userInfoDao.findOne(id);
    }

    @Cacheable(key = "targetClass + methodName")
    public List<Map> onlineUserList() {
        DefaultWebSecurityManager securityManager = (DefaultWebSecurityManager) SecurityUtils.getSecurityManager();
        DefaultWebSessionManager sessionManager = (DefaultWebSessionManager) securityManager.getSessionManager();
        Collection<Session> sessions = sessionManager.getSessionDAO().getActiveSessions();//获取当前已登录的用户session列表
        List<Map> list = new ArrayList<>();
        for (Session session : sessions) {
            if (session == null) {
                continue;
            }
            Map map = Maps.newHashMap();
            String username = "";
            //principalCollection 身份
            SimplePrincipalCollection principalCollection = new SimplePrincipalCollection();
            if (session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY) == null) {
                continue;
            } else {
                principalCollection = (SimplePrincipalCollection) session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY);
                username = (String) principalCollection.getPrimaryPrincipal();
                //处理手机端登录token 获取用户名
                if(username.length() > 20){
                    username = JwTUtils.getUsername(username);
                }
                map.put("username", username);
            }
            map.put("sessionId", session.getId().toString());
            map.put("host", session.getHost());
            map.put("lastAccessTime", DateUtils.dateToStringFormat(session.getLastAccessTime(), "yyyy-MM-dd HH:mm:ss.SSS"));
            map.put("startTimestamp", DateUtils.dateToStringFormat(session.getStartTimestamp(), "yyyy-MM-dd HH:mm:ss.SSS"));
            map.put("timeout", session.getTimeout());
            list.add(map);
        }
        return list;
    }

    @CacheEvict(value = {"userInfoCache", "sysRoleCache", "sysPermissionCache"}, allEntries = true)
    @Transactional
    public UserInfo getUserByGuid(String guid) {
        String hql = "from UserInfo u where u.guid=:guid";
        Map<String,Object> map = new HashMap<>();
        map.put("guid",guid);
        List<UserInfo> list = this.findHql(hql, map);
        return list.size() > 0 ? (UserInfo)list.get(0) : null;
    }

    /**
     * 分页处理
     *查询物业所需
     * @return
     */
    public PageBean<UserInfo> getUserInfoForPropertyPageBeen() {
        //查询语句
        UserInfo userInfo= WebUtils.getLoginUserInfo();
        StringBuffer query = new StringBuffer("distinct u from UserInfo u left join u.roleList r left join u.department d");
        //分页数据防止重复：多表关联
        StringBuffer countQuery = new StringBuffer("count(distinct u)");
        //默认排序(PageBean指定排序字段类型的话，则默认排序不使用)
        StringBuffer orderBy = new StringBuffer("u.id desc,u.state desc");

        Wrapper wrapper = new Wrapper(query, countQuery, orderBy);
        Set<SysRole> roleList=userInfo.getRoleList();
        for (SysRole sysRole:roleList){
            if (sysRole.getRole().equals("物业管理员")){
                wrapper.andLike("r.role","物业");
            }
        }

        wrapper.initSearchParams();

        return this.pageHql(wrapper);
    }
}